package ke03.am;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;

public class CsvDatabase2 implements Database {

	private final Set<Integer> givenKeys = new HashSet<Integer>();
	private final String file;

	public CsvDatabase2(String file) {
		this.file = file;
	}

	@Override
	public boolean write(int key, Vector<?> v) {
		if (v == null || key == 0 || !givenKeys.add(key)) {
			return false;
		}
		String asCsv = vectorToCsv(key, v);
		// key = 3; Vector = ["eins", "zwei", "drei"] -> "3;eins;zwei;drei"
		try {
			FileWriter writer = new FileWriter(file, true);
			BufferedWriter bufWriter = new BufferedWriter(writer);
			bufWriter.write(asCsv);
			bufWriter.newLine();
			bufWriter.close();
			return true;
		} catch (IOException e) {

		}
		return false;
	}

	/**
	 * Converts a vector into a CSV format representation, with a preceeding key
	 * value. CSV format: <key>;<entry1>;<entry2>;...;<entryN>
	 * 
	 * @param key
	 *            the key.
	 * @param v
	 *            the vector.
	 * @return a CSV representation of the vector.
	 */
	private String vectorToCsv(int key, Vector<?> v) {
		StringBuffer buffer = new StringBuffer();
		buffer.append(key).append(";");
		for (int i = 0; i < v.size(); i++) {
			Object e = v.elementAt(i);
			buffer.append(";").append(e);
		}

		return buffer.toString();
	}

	@Override
	public Vector<?> read(int key) {
		if (!givenKeys.contains(key)) {
			return null;
		}
		FileReader reader = null;
		try {
			reader = new FileReader(file);
			BufferedReader bufReader = new BufferedReader(reader);
			String row;
			while ((row = bufReader.readLine()) != null) {
				if (row.startsWith("" + key + ";")) {
					Vector<?> v = csvToVector(row);
					return v;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (reader != null) {
					reader.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}

	private Vector<?> csvToVector(String csvString) {
		Vector<String> v = new Vector<String>();
		String[] values = csvString.split(";");
		for (int i = 1; i < values.length; i++) {
			v.add(values[i]);
		}
		return v;
	}

	@Override
	public boolean drop() {
		File physicalFile = new File(file);
		if (!physicalFile.exists()) {
			givenKeys.clear();
			return true;
		}
		boolean success = physicalFile.delete();
		return success;
	}

	@Override
	public boolean delete(int key) {
		String zeile = null;

		try {
			RandomAccessFile f = new RandomAccessFile(file, "rw");
			boolean cont = true;
			while (cont) {
				long pointer = f.getFilePointer();
				zeile = f.readLine();
				if (zeile != null) {
					if (zeile.startsWith(key + ";")) {
						f.seek(pointer);
						f.writeBytes("0");
						cont = false;
					}
				} else {
					cont = false;
				}
			}
			f.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (zeile != null) {
			givenKeys.remove(key);
			return true;
		}
		return false;
	}

}
